﻿//----------------------------------------------------------------
// Desc: 匀变速直线运动动画处理器，中间物理插值
// Edit: ShowLong, http://blog.csdn.net/showlong
//
// Date Created: 2011-01-10
//
// Update Date : 
//
// Copyright (c) Fuel Game Engine (http://www.fge-engine.com), All rights reserved.
//
//----------------------------------------------------------------
#pragma once


#include "FKeyAnimation.h"


class FMoveAnimation : public IFMemObject
{
    FDECLARE_CLASS(FMoveAnimation)

public:
    FMoveAnimation();
    ~FMoveAnimation();

    struct FKEY
    {
        friend class FMoveAnimation;

    private:
        float ntime;        // 上一个时间点到现在时间点的时长(秒)
        float nspeed;       // 此时间点的瞬时速度(米/秒)
        // 以上两个参数意思可表达为：5秒后速度达到20米/秒，再过3.5秒后速度达到47米/秒，再过5秒后速度为50米/秒，共三个关键时间点

    public:
        FKeyAnimation::FKEY* pk; // 运动过程中计算出来的关键帧信息，可直接使用

        FKEY(){ ntime=nspeed=0; pk=0; pttime=local=0; }
        FKEY(float t, float s){ ntime=t,nspeed=s; pk=0; pttime=local=0; }
        // 取得从起点到本时间点的总时长
        float GetTime(){ return pttime; }
        // 取得从起点到本时间点的总距离
        float GetLocal(){ return local; }
        // 取得当时的速度
        float GetSpeed(){ return nspeed; }

    private:
        float pttime;   // 总的时间位置
        float local;    // 总的距离位置
    };

    typedef_vector(FKEY, _fkey);

    // 绑上一个动画
    // .pai 路程关键帧数据，参数pai::FKEY::frame必须是表示距离起点的路程
    void Attach(FKeyAnimation* pai);
    // 刷新动画，以便于更新当前位置
    void Update();
    // 在前一个时间点的基础上补充一个时间点
    // .key 本时间点的信息
    // .is_first 是否是第一个时间点
    void Append(FKEY& key, bool is_first);
    // 开始播放，以每秒40帧速度刷新()
    void Play();
    // 停止
    void Stop();
    // 取指定时间位置的数据(单位:秒)
    // .ntime 总的时间点，ntime<=0 表示起点的时间
    // .key 输出该时间点数据
    void GetKey(float ntime, FMoveAnimation::FKEY* key);
    // 设置当前时间位置
    void SetCurKey(float ntime){ GetKey(ntime, &nCurKey); }
    // 取当前时间位置的数据
    FMoveAnimation::FKEY* GetCurKey(){ FASSERT(pTrackAnim, _T("没有初始化")); return &nCurKey; }
    // 当前是否播放中
    bool IsVaild(){ return pTrackAnim != 0; }
    // 当前是否正在播放中
    bool IsPlaying(){ return bPlaying; }
    // 当前是否已经完成动画
    bool IsDone(){ bool x = bIsDone; bIsDone = false; return x; }
    // 快进或后退多少秒
    void SetTime(float ntime){ fStartTime -= (ntime * 1000.0f); }
    // 设置结束时停在头还在尾
    void SetStopAt(bool end){ bStopInEnd = end; }
    // 取动关键点总数
    int GetKeyCount(){ return (int)vKeyList.size(); };
    // 取队列中首个关键时间点
    FMoveAnimation::FKEY* GetFirstKey(){ return &vKeyList[0]; }
    // 取队列中最尾个关键时间点
    FMoveAnimation::FKEY* GetEndKey(){ return &vKeyList[vKeyList.size() - 1]; }


protected:
    bool bStopInEnd;    // 默认true
    bool bPlaying;
    float fStartTime;
    FKeyAnimation* pTrackAnim;
    FKeyAnimation::FKEY nCache;
    FMoveAnimation::FKEY nCurKey;
    fv_fkey vKeyList;
    DWORD nLastUpdate;
    bool bIsDone;
};